package com.thinkit.bigdata.web.service.impl.audioSearch;

import com.google.common.base.Strings;
import com.thinkit.bigdata.core.util.es.ESUtil;
import com.thinkit.bigdata.web.controller.pubmet.PubMethod;
import com.thinkit.bigdata.web.coremet.SystemStatic;
import com.thinkit.bigdata.web.model.BaseEntity;
import com.thinkit.bigdata.web.model.es.audioEs.Source;
import com.thinkit.bigdata.web.model.es.audioEs.TestInfos;
import com.thinkit.bigdata.web.model.es.audioEs.WorkScores;
import com.thinkit.bigdata.web.model.result.HtmlResult;
import com.thinkit.bigdata.web.service.audioSearch.TaskAudioSeaService;
import com.thinkit.bigdata.web.service.impl.perCenter.perCenterServiceImpl;
import org.apache.log4j.Logger;
import org.apache.lucene.search.join.ScoreMode;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.NestedQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 *
 * Created by hccl on 2018/9/18.
 */
@Service
public class TaskAudioSeaServiceImpl implements TaskAudioSeaService {

    private static Logger logger = Logger.getLogger(perCenterServiceImpl.class);

    @Resource
    private ESUtil esUtil;

    @Override
    public BoolQueryBuilder getQuery(String logTxt, HttpServletRequest request) {
        String provinceCode = request.getParameter("provinceCode");//省份
        String callDirection = request.getParameter("callDirection");//呼叫类型
        String serialNumbers = request.getParameter("serialNumber");//录音流水
        String seatGroup = request.getParameter("seatGroup");//坐席班组
        String seatId = request.getParameter("seatId");//坐席工号
        String seatName = request.getParameter("seatName");//坐席工号
        String proPhoneNum = request.getParameter("proPhoneNum");//受理号码
        String customerNumber = request.getParameter("customerNumber");//客户号码
        String customerLevels = request.getParameter("customerLevel");//客户星级
        String customerlocs = request.getParameter("customerloc");//客户归属地
        String customerSign = request.getParameter("customerSign");//重要客户
        String onHooks = request.getParameter("onHook");//挂机方
        String callStartTime = request.getParameter("callStartTime");//通话开始时间
        String callEndTime = request.getParameter("callEndTime");//通话结束时间
        String holdDurationMin = request.getParameter("holdDurationMin");//通话时长小值
        String holdDurationMax = request.getParameter("holdDurationMax");//通话时长大值
        String scoreMin = request.getParameter("scoreMin");//通话时长大值
        String scoreMax = request.getParameter("scoreMax");//通话时长大值
        String reCallFlag = request.getParameter("reCallFlag");//重复来电
        String satisfactions = request.getParameter("satisfaction");//满意度
        String workId = request.getParameter("workId");//质检任务名称
        String preQualitys = request.getParameter("preQuality");//质检类型
        String proStatus = request.getParameter("proStatus");//质检状态
        String proFlag = request.getParameter("proFlag");//质检属性
        String inValid = request.getParameter("inValid");//过期
        String ruleId = request.getParameter("ruleId");//规则id
        //规则统计类型 总命中量(hitCount) 系统命中量(sysHitCount) 人工添加量(leakageCount)
        // 人工纠正量(accuracyCount) 申诉量(appealCount) 驳回量(rejectCount) 申诉成功量(appealOkCount)
        String ruleType = request.getParameter("ruleType");
        String inputTimeBegin = request.getParameter("inputTimeBegin");//入库时间
        String inputTimeEnd = request.getParameter("inputTimeEnd");//入库时间
        String sysTagIds = request.getParameter("sysTagIds");//系统标签_标签ids
        String sysOperator = request.getParameter("sysOperator");//系统标签_运算符  //should  ||   must
        String telTagIds = request.getParameter("telTagIds");//话务小结_标签ids
        String telOperator = request.getParameter("telOperator");//话务小结_运算符  //should  ||   must
        logger.info(logTxt + "provinceCode = " + provinceCode);
        logger.info(logTxt + "workId = " + workId);
        logger.info(logTxt + "preQualitys = " + preQualitys);
        logger.info(logTxt + "callDirection = " + callDirection);
        logger.info(logTxt + "serialNumbers = " + serialNumbers);
        logger.info(logTxt + "seatGroup = " + seatGroup);
        logger.info(logTxt + "seatId = " + seatId);
        logger.info(logTxt + "seatName = " + seatName);
        logger.info(logTxt + "proPhoneNum = " + proPhoneNum);
        logger.info(logTxt + "customerNumber = " + customerNumber);
        logger.info(logTxt + "customerLevel = " + customerLevels);
        logger.info(logTxt + "customerloc = " + customerlocs);
        logger.info(logTxt + "customerSign = " + customerSign);
        logger.info(logTxt + "onHooks = " + onHooks);
        logger.info(logTxt + "callStartTime = " + callStartTime);
        logger.info(logTxt + "callEndTime = " + callEndTime);
        logger.info(logTxt + "holdDurationMin = " + holdDurationMin);
        logger.info(logTxt + "holdDurationMax = " + holdDurationMax);
        logger.info(logTxt + "reCallFlag = " + reCallFlag);
        logger.info(logTxt + "satisfactions = " + satisfactions);
        logger.info(logTxt + "proStatus = " + proStatus);
        logger.info(logTxt + "proFlag = " + proFlag);
        logger.info(logTxt + "inValid = " + inValid);
        logger.info(logTxt + "ruleId = " + ruleId);
        logger.info(logTxt + "inputTimeBegin = " + inputTimeBegin);
        logger.info(logTxt + "inputTimeEnd = " + inputTimeEnd);
        logger.info(logTxt + "sysTagIds = " + sysTagIds);
        logger.info(logTxt + "sysOperator = " + sysOperator);
        logger.info(logTxt + "ruleType = " + ruleType);
        logger.info(logTxt + "telTagIds = " + telTagIds);
        logger.info(logTxt + "telOperator = " + telOperator);
        logger.info(logTxt + "scoreMin = " + scoreMin);
        logger.info(logTxt + "scoreMax = " + scoreMax);
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //数据权限
        esUtil.formatQ(boolQuery, seatId);
        //serialNumber
        if (!Strings.isNullOrEmpty(serialNumbers)) {
            BoolQueryBuilder shuldQ = new BoolQueryBuilder();
            for (String serialNumber : serialNumbers.split(",")) {
                shuldQ.should(QueryBuilders.wildcardQuery("serialNumber", "*" + serialNumber + "*"));
            }
            boolQuery.must(shuldQ);
        }
        if (!Strings.isNullOrEmpty(provinceCode)) {
            boolQuery.must(QueryBuilders.matchQuery("voiceInfo.provinceCode", provinceCode));
        }
        if (!Strings.isNullOrEmpty(callDirection)) {
            boolQuery.must(QueryBuilders.matchQuery("voiceInfo.callDirection", callDirection));
        }
        //挂机方
        if (!Strings.isNullOrEmpty(onHooks)) {
            PubMethod.formatOnHook(boolQuery, Arrays.asList(onHooks.split(",")));
        }
        if (!Strings.isNullOrEmpty(customerNumber)) {
            boolQuery.must(QueryBuilders.wildcardQuery("voiceInfo.customerNum", "*" + customerNumber + "*"));
        }
        if (!Strings.isNullOrEmpty(proPhoneNum)) {
            boolQuery.must(QueryBuilders.wildcardQuery("voiceInfo.proPhoneNum", "*" + proPhoneNum + "*"));
        }
        //客户归属地
        if (!Strings.isNullOrEmpty(customerlocs)) {
            PubMethod.formatPC(boolQuery, Arrays.asList(customerlocs.split(",")));
        }
        //客户星级
        if (!Strings.isNullOrEmpty(customerLevels)) {
            PubMethod.formatCustomerLevel(boolQuery, Arrays.asList(customerLevels.split(",")));
        }
        if (!Strings.isNullOrEmpty(customerSign)) {
            boolQuery.must(QueryBuilders.matchQuery("voiceInfo.customerSign", customerSign));
        }
        if (!Strings.isNullOrEmpty(reCallFlag)) {
            boolQuery.must(QueryBuilders.matchQuery("voiceInfo.reCallFlag", reCallFlag));
        }
        //满意度
        if (!Strings.isNullOrEmpty(satisfactions)) {
            PubMethod.formatSatisfactions(boolQuery, Arrays.asList(satisfactions.split(",")));
        }
        if (!Strings.isNullOrEmpty(seatName)) {
            boolQuery.must(QueryBuilders.matchQuery("voiceInfo.seatName", seatName));
        }
        //班组标识
        if (!Strings.isNullOrEmpty(seatGroup)) {
            BoolQueryBuilder shuldQ = new BoolQueryBuilder();
            for (String groupId : seatGroup.split(",")) {
                shuldQ.should(QueryBuilders.matchQuery("voiceInfo.groupId", groupId));
            }
            boolQuery.must(shuldQ);
        }
        if (!Strings.isNullOrEmpty(callStartTime)) {
            PubMethod.formatTime(boolQuery, callStartTime, callEndTime);
        }
        if (!Strings.isNullOrEmpty(inputTimeBegin)) {
            boolQuery.must(QueryBuilders.rangeQuery("voiceInfo.inputTime").gte(inputTimeBegin));
        }
        if (!Strings.isNullOrEmpty(inputTimeEnd)) {
            boolQuery.must(QueryBuilders.rangeQuery("voiceInfo.inputTime").lte(inputTimeEnd));
        }
        if (!Strings.isNullOrEmpty(holdDurationMin)) {
            boolQuery.must(QueryBuilders.rangeQuery("voiceInfo.holdDuration").gte(holdDurationMin));
        }
        if (!Strings.isNullOrEmpty(holdDurationMax)) {
            boolQuery.must(QueryBuilders.rangeQuery("voiceInfo.holdDuration").lte(holdDurationMax));
        }
        //系统标签
        if (!Strings.isNullOrEmpty(sysTagIds)) {
            BoolQueryBuilder shouldOrMustQ = new BoolQueryBuilder();
            for (String tagName : sysTagIds.split(",")) {
                NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(
                        "callTags",
                        QueryBuilders.boolQuery()
                                .must(QueryBuilders.wildcardQuery("callTags.tagName", tagName + "*"))
                                .mustNot(QueryBuilders.matchQuery("callTags.proType", BaseEntity.PROTYPE_ZX)),
                        ScoreMode.None
                );
                if ("0".equals(sysOperator)) {
                    shouldOrMustQ.should(nestedQueryBuilder);
                } else {
                    shouldOrMustQ.must(nestedQueryBuilder);
                }
            }
            boolQuery.must(shouldOrMustQ);
        }
        //话务小结
        if (!Strings.isNullOrEmpty(telTagIds)) {
            BoolQueryBuilder shouldOrMustQ = new BoolQueryBuilder();
            for (String tagName : telTagIds.split(",")) {
                NestedQueryBuilder nestedQueryBuilder = QueryBuilders.nestedQuery(
                        "callTags",
                        QueryBuilders.boolQuery()
                                .must(QueryBuilders.wildcardQuery("callTags.tagName", tagName + "*"))
                                .must(QueryBuilders.matchQuery("callTags.proType", BaseEntity.PROTYPE_ZX)),
                        ScoreMode.None
                );
                if ("0".equals(telOperator)) {
                    shouldOrMustQ.should(nestedQueryBuilder);
                } else {
                    shouldOrMustQ.must(nestedQueryBuilder);
                }
            }
            boolQuery.must(shouldOrMustQ);
        }
        List<Integer> proStatusList = new ArrayList<>();
        //质检状态不为空，过期状态为空  -->  查询 该质检状态所有的
        if (!Strings.isNullOrEmpty(proStatus) && Strings.isNullOrEmpty(inValid)) {
            for (String pro : proStatus.split(",")) {
                proStatusList.addAll(esUtil.proStatusList(Integer.parseInt(pro)));
            }
        }
        //质检状态不为空，过期状态过期  -->  查询 该质检过期的
        if (!Strings.isNullOrEmpty(proStatus) && !Strings.isNullOrEmpty(inValid) && "7".equals(inValid)) {
            for (String pro : proStatus.split(",")) {
                proStatusList.addAll(esUtil.proStatusInValidList(Integer.parseInt(pro)));
            }
        }
        //质检状态不为空，过期状态不过期  -->  查询 该质检不过期的
        if (!Strings.isNullOrEmpty(proStatus) && !Strings.isNullOrEmpty(inValid) && !"7".equals(inValid)) {
            for (String pro : proStatus.split(",")) {
                proStatusList.addAll(esUtil.proStatusValidList(Integer.parseInt(pro)));
            }
        }
        //质检状态为空，过期状态过期  -->  查询 所有过期的状态
        if (Strings.isNullOrEmpty(proStatus) && !Strings.isNullOrEmpty(inValid) && "7".equals(inValid)) {
            proStatusList = esUtil.validList();
        }
        //质检状态为空，过期状态不过期  -->  查询 所有不过期的状态
        if (Strings.isNullOrEmpty(proStatus) && !Strings.isNullOrEmpty(inValid) && !"7".equals(inValid)) {
            proStatusList = esUtil.inValidList();
        }
        BoolQueryBuilder queryBuilder = new BoolQueryBuilder();
        queryBuilder.must(QueryBuilders.matchQuery("workScores.workId", workId));
        if (!proStatusList.isEmpty()) {
            BoolQueryBuilder shuldQ = new BoolQueryBuilder();
            for (Integer proS : proStatusList) {
                shuldQ.should(QueryBuilders.matchQuery("workScores.proStatus", proS));
            }
            queryBuilder.must(shuldQ);
        }
        if (!Strings.isNullOrEmpty(preQualitys)) {
            BoolQueryBuilder shuldQ = new BoolQueryBuilder();
            for (String preQuality : preQualitys.split(",")) {
                shuldQ.should(QueryBuilders.matchQuery("workScores.preQuality", preQuality));
            }
            queryBuilder.must(shuldQ);
        }
        if (!Strings.isNullOrEmpty(proFlag)) {
            queryBuilder.must(QueryBuilders.matchQuery("workScores.proFlag", proFlag));
        }
        if (!Strings.isNullOrEmpty(scoreMin)) {
            queryBuilder.must(QueryBuilders.rangeQuery("workScores.workScore").gte(scoreMin));
        }
        if (!Strings.isNullOrEmpty(scoreMax)) {
            queryBuilder.must(QueryBuilders.rangeQuery("workScores.workScore").lte(scoreMax));
        }
        if (!Strings.isNullOrEmpty(ruleId)) {
            queryBuilder.must(
                    QueryBuilders.nestedQuery(
                            "workScores.modelRules",
                            QueryBuilders.matchQuery("workScores.modelRules.ruleId", ruleId),
                            ScoreMode.None
                    )
            );
        }
        boolQuery.must(QueryBuilders.nestedQuery(
                "workScores",
                queryBuilder,
                ScoreMode.None)
        );
        //总命中量查询时候，排除申诉成功的量,人工纠错的量
        if (!Strings.isNullOrEmpty(ruleId) && "hitCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    )
                                    .mustNot(
                                            QueryBuilders.nestedQuery(
                                                    "ruleInfos.ruleDetails.processedInfos",
                                                    QueryBuilders.matchQuery("ruleInfos.ruleDetails.processedInfos.proStatus", BaseEntity.SM_WORK_PROSTATUS_APPEAL_YES),
                                                    ScoreMode.None
                                            )
                                    )
                                    .mustNot(
                                            QueryBuilders.nestedQuery(
                                                    "ruleInfos.ruleDetails",
                                                    QueryBuilders.boolQuery()
                                                            .must(QueryBuilders.matchQuery("ruleInfos.ruleDetails.matchStatus", BaseEntity.MATCHSTATUS_NO))
                                                            .must(QueryBuilders.matchQuery("ruleInfos.ruleDetails.proStatus", BaseEntity.SM_WORK_PROSTATUS_APPEAL_BEGIN)),
                                                    ScoreMode.None
                                            )
                                    )
                            ,
                            ScoreMode.None
                    )
            );
        }
        //系统命中量查询时候，排除漏识的量
        if (!Strings.isNullOrEmpty(ruleId) && "sysHitCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    ).must(
                                    QueryBuilders.nestedQuery(
                                            "ruleInfos.ruleDetails",
                                            QueryBuilders.matchQuery("ruleInfos.ruleDetails.isMissing", BaseEntity.ISMISSING_NO),
                                            ScoreMode.None
                                    )
                            ),
                            ScoreMode.None
                    )
            );
        }
        //人工添加量查询
        if (!Strings.isNullOrEmpty(ruleId) && "leakageCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    ).must(
                                            QueryBuilders.nestedQuery(
                                                    "ruleInfos.ruleDetails",
                                                    QueryBuilders.matchQuery("ruleInfos.ruleDetails.isMissing", BaseEntity.ISMISSING_YES),
                                                    ScoreMode.None
                                            )
                            ),
                            ScoreMode.None
                    )
            );
        }
        //人工纠正量查询
        if (!Strings.isNullOrEmpty(ruleId) && "accuracyCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    ).must(
                                            QueryBuilders.nestedQuery(
                                                    "ruleInfos.ruleDetails",
                                                    QueryBuilders.boolQuery()
                                                            .must(QueryBuilders.matchQuery("ruleInfos.ruleDetails.matchStatus", BaseEntity.MATCHSTATUS_NO))
                                                            .must(QueryBuilders.matchQuery("ruleInfos.ruleDetails.proStatus", BaseEntity.SM_WORK_PROSTATUS_APPEAL_BEGIN)),
                                                    ScoreMode.None
                                            )
                            ),
                            ScoreMode.None
                    )
            );
        }
        //申诉量查询
        if (!Strings.isNullOrEmpty(ruleId) && "appealCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    ).mustNot(
                                            QueryBuilders.nestedQuery(
                                                    "ruleInfos.ruleDetails",
                                                    QueryBuilders.matchQuery("ruleInfos.ruleDetails.proStatus", BaseEntity.SM_WORK_PROSTATUS_APPEAL_BEGIN),
                                                    ScoreMode.None
                                    )
                            ),
                            ScoreMode.None
                    )
            );
        }
        //驳回量查询
        if (!Strings.isNullOrEmpty(ruleId) && "rejectCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    ).must(
                                    QueryBuilders.nestedQuery(
                                            "ruleInfos.ruleDetails.processedInfos",
                                            QueryBuilders.boolQuery().mustNot(
                                                    QueryBuilders.matchQuery("ruleInfos.ruleDetails.processedInfos.proStatus", BaseEntity.SM_WORK_PROSTATUS_APPEAL_YES)
                                            ),
                                            ScoreMode.None
                                    )
                            ),
                            ScoreMode.None
                    )
            );
        }
        //申诉成功量查询
        if (!Strings.isNullOrEmpty(ruleId) && "appealOkCount".equals(ruleType)) {
            boolQuery.must(
                    QueryBuilders.nestedQuery(
                            "ruleInfos",
                            QueryBuilders.boolQuery()
                                    .must(
                                            QueryBuilders.matchQuery("ruleInfos.ruleId", ruleId)
                                    ).must(
                                    QueryBuilders.nestedQuery(
                                            "ruleInfos.ruleDetails.processedInfos",
                                            QueryBuilders.matchQuery("ruleInfos.ruleDetails.processedInfos.proStatus", BaseEntity.SM_WORK_PROSTATUS_APPEAL_YES),
                                            ScoreMode.None
                                    )
                            ),
                            ScoreMode.None
                    )
            );
        }
        return boolQuery;
    }

    @Override
    public HtmlResult audioNlpStatus(String serialNumber, String workId, String type) {
        BoolQueryBuilder boolQuery = new BoolQueryBuilder();
        boolQuery.must(QueryBuilders.matchQuery("serialNumber", serialNumber));
        String[] includes = new String[]
                {
                        "serialNumber",
                        "workScores.workId",
                        "workScores.nlpRtnCode",
                        "testInfos.workId",
                        "testInfos.nlpRtnCode"
                };
        List<String> docList = SystemStatic.crud.queryMapQBuilderRetRuleAndWork(
                SystemStatic.AUDIO_ES_INDEX,
                SystemStatic.AUDIO_ES_TYPE,
                0,
                1,
                boolQuery,
                "",
                "",
                includes
        );
        Source source = esUtil.str2entity(docList.get(0));
        if ("work".equals(type)) {
            for (WorkScores workScores : source.getWorkScores()) {
                if (workId.equals(workScores.getWorkId().toString())) {
                    return HtmlResult.success(workScores.getNlpRtnCode());
                }
            }
        }
        if ("test".equals(type)) {
            for (TestInfos testInfos : source.getTestInfos()) {
                if (workId.equals(testInfos.getWorkId().toString())) {
                    return HtmlResult.success(testInfos.getNlpRtnCode());
                }
            }
        }
        return HtmlResult.failure();
    }

    @Override
    public HtmlResult searchData(HttpServletRequest request) {
        String logTxt = "【音频检索方法Impl】";
        logger.info(logTxt);
        String workId = request.getParameter("workId");//质检任务名称
        if (Strings.isNullOrEmpty(workId)) {
            return HtmlResult.success(new ArrayList<>());
        }
        String pageNum = request.getParameter("pageNum");//起始页
        String pageSize = request.getParameter("pageSize");//每页条数
        String sortName = request.getParameter("sortName");//录音流水
        String sortOrder = request.getParameter("sortOrder");//录音流水
        BoolQueryBuilder boolQuery = getQuery(logTxt, request);
        String[] includes = new String[]
                {
                        "serialNumber",
                        "voiceInfo",
                        "ruleInfos.ruleDetails.processedInfos.proTime",
                        "ruleInfos.ruleDetails.processedInfos.proUserId",
                        "workScores.workId",
                        "workScores.workName",
                        "workScores.proStatus",
                        "workScores.proUserName",
                        "workScores.proFlag",
                        "workScores.workScore",
                        "workScores.inputTime",
                        "workScores.updateTime",
                        "workScores.preQuality"
                };
        List<String> docList = SystemStatic.crud.queryMapQBuilderRetRuleAndWork(
                SystemStatic.AUDIO_ES_INDEX,
                SystemStatic.AUDIO_ES_TYPE,
                Integer.parseInt(pageNum),
                Integer.parseInt(pageSize),
                boolQuery,
                SystemStatic.crud.formatCloumn(sortName, SystemStatic.AUDIO_ES_INDEX),
                sortOrder,
                includes
        );
        logger.info(logTxt + "获取数据条数为：" + docList.size());
        return HtmlResult.success(
                esUtil.formatModel(docList, workId),
                SystemStatic.crud.queryQBuilderAllByMes(SystemStatic.AUDIO_ES_INDEX, SystemStatic.AUDIO_ES_TYPE, boolQuery)
        );
    }
}
